package org.jsola.hr.service.impl;

import org.jsola.core.Page;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IEmpSocItemDAO;
import org.jsola.hr.dto.EmpSocItemAddDTO;
import org.jsola.hr.dto.EmpSocItemDTO;
import org.jsola.hr.dto.EmpSocItemUpdateDTO;
import org.jsola.hr.dto.syncSocDTO.QingDaoCardinalityDefaultDTO;
import org.jsola.hr.entity.EmpSocInfoDO;
import org.jsola.hr.entity.EmpSocItemDO;
import org.jsola.hr.query.EmpSocItemQuery;
import org.jsola.hr.service.IEmpSocInfoService;
import org.jsola.hr.service.IEmpSocItemService;
import org.jsola.hr.service.IEmpSocTransformService;
import org.jsola.hr.vo.EmpSocInfoVO;
import org.jsola.hr.vo.EmpSocItemListVO;
import org.jsola.hr.vo.EmpSocItemVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.jsola.hr.constant.MantissaProcessingType.NOT_PROCESSING;

/**
 * 员工参保信息表子项
 *
 * @author zhr
 */
@Service("hrEmpSocItemServiceImpl")
public class EmpSocItemServiceImpl implements IEmpSocItemService {

    @Autowired
    private IEmpSocItemDAO empSocItemDAO;

    @Autowired
    private IEmpSocItemService empSocItemService;

    @Autowired
    private IEmpSocInfoService empSocInfoService;

    @Autowired
    private IEmpSocTransformService empSocTransformService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpSocItemVO save(EmpSocItemAddDTO empSocItemAddDTO, TokenUser tokenUser) {
        // 转DO
        EmpSocItemDO empSocItemDO = empSocItemAddDTO.to(EmpSocItemDO.class);
        // 保存
        empSocItemDO = save(empSocItemDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return empSocItemDO.to(EmpSocItemVO.class);
    }

    @Override
    public Integer onlySave(EmpSocItemDO empSocItemDO) {

        return empSocItemDAO.insert(empSocItemDO);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public List<EmpSocItemVO> batchSave(List<EmpSocItemAddDTO> empSocItemAddDTOList, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(empSocItemAddDTOList)) {
            return null;
        }
        List<EmpSocItemDO> empSocItemDOList = empSocItemAddDTOList
                .parallelStream()
                .map(empSocItemAddDTO -> {
                    EmpSocItemDO empSocItemDO = empSocItemAddDTO.to(EmpSocItemDO.class);
                    empSocItemDO.preInsert(tokenUser.getUserId());
                    empSocItemDO.setSiteId(tokenUser.getSiteId());
                    return empSocItemDO;
                }).collect(Collectors.toList());
        empSocItemDAO.insertListAndSetId(empSocItemDOList);
        return empSocItemDOList
                .parallelStream()
                .map(empSocItemDO -> empSocItemDO.to(EmpSocItemVO.class))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(EmpSocItemUpdateDTO empSocItemUpdateDTO, TokenUser tokenUser) {
        //转DO
        EmpSocItemDO empSocItemDO = empSocItemUpdateDTO.to(EmpSocItemDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(empSocItemDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... empSocItemIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) empSocItemIds);
    }


    @Override
    public EmpSocItemVO selectById(String empSocItemId, String siteId) {
        EmpSocItemDO empSocItemDO = selectDOById(empSocItemId, siteId);
        if (empSocItemDO == null) {
            return null;
        }
        return empSocItemDO.to(EmpSocItemVO.class);
    }

    @Override
    public List<EmpSocItemListVO> select(EmpSocItemQuery empSocItemQuery, String siteId) {
        List<EmpSocItemDO> empSocItemDOList = selectDO(empSocItemQuery, siteId);
        if (CollectionUtils.isEmpty(empSocItemDOList)) {
            return empSocItemDOList == null ? null : new ArrayList<>();
        }
        return empSocItemDOList.stream()
                .map(empSocItemDO -> empSocItemDO.to(EmpSocItemListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(EmpSocItemQuery empSocItemQuery, String siteId) {
        Example example = buildExample(empSocItemQuery, siteId);
        return empSocItemDAO.selectCountByExample(example);
    }

    @Override
    public Page<EmpSocItemListVO> selectPage(EmpSocItemQuery empSocItemQuery, String siteId) {
        Example example = buildExample(empSocItemQuery, siteId);
        Page<EmpSocItemDO> page = empSocItemDAO.selectPageByExample(example,
                empSocItemQuery.getPageNo(),
                empSocItemQuery.getPageSize());

        return page.to(EmpSocItemListVO.class);
    }

    @Override
    public EmpSocItemDO selectDOById(String empSocItemId, String siteId) {
        return listById(empSocItemId, siteId);
    }

    @Override
    public List<EmpSocItemDO> selectDO(EmpSocItemQuery empSocItemQuery, String siteId) {
        Example example = buildExample(empSocItemQuery, siteId);
        return empSocItemDAO.selectByExample(example);
    }

    @Override
    public List<EmpSocItemDO> selectByEmpSocId(String empSocId, String siteId) {
        Example example = new Example(EmpSocItemDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("empSocId", empSocId);
        return empSocItemDAO.selectByExample(example);
    }

    @Override
    public List<EmpSocItemDO> selectByEmpSocIdList(List<String> empSocIdList, String siteId) {
        if (CollectionUtils.isEmpty(empSocIdList)) {
            return new ArrayList<>();
        }
        return empSocItemDAO.selectByEmpSocIdList(empSocIdList, siteId);
    }

    @Override
    public EmpSocItemDO selectEmpSocItemByInfoIdAndName(String siteId, String itemName, String empSocId) {
        Example example = new Example(EmpSocItemDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("itemName", itemName)
                .andEqualTo("empSocId", empSocId);
        return empSocItemDAO.selectOneByExample(example);
    }

    @Override
    public List<EmpSocItemDO> selectEmpSocItemByInfoId(String empSocId, String siteId) {
        Example example = new Example(EmpSocItemDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("empSocId", empSocId);
        return empSocItemDAO.selectByExample(example);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void saveItemWithIncrement(List<EmpSocItemDTO> empSocItemDTOList, EmpSocInfoDO empSocInfoDO, TokenUser tokenUser) {
        String empSocId = empSocInfoDO.getId();
        List<EmpSocItemDO> empSocItemDOList = empSocItemDTOList.stream().map(
                empSocItemDTO -> {
                    EmpSocItemDO empSocItemDO = empSocItemDTO.to(EmpSocItemDO.class);
                    if (empSocItemDO.getCardinalityDefault().compareTo(empSocItemDO.getCardinalityMin()) < 0) {
                        empSocItemDO.setCardinalityDefault(empSocItemDO.getCardinalityMin());
                    }
                    empSocItemDO.setId(null);
                    empSocItemDO.setEmpSocId(empSocId);
                    empSocItemDO.preInsert(tokenUser.getUserId());
                    empSocItemDO.setSiteId(tokenUser.getSiteId());
                    return empSocItemDO;
                }
        ).collect(Collectors.toList());
        // 批量保存
        empSocItemDAO.insertListAndSetId(empSocItemDOList);
    }

    @Override
    public void batchDeleteByEmpSocInfoIdList(List<String> empSocInfoIdList) {
        Example example = new Example(EmpSocItemDO.class);
        example.and().andIn("empSocId", empSocInfoIdList);
        empSocItemDAO.deleteByExample(example);
    }

    @Override
    public List<EmpSocItemDO> selectPfByEmpSocInfoId(String empSocInfoId, String siteId) {
        Example example = new Example(EmpSocItemDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("empSocId", empSocInfoId)
                .andEqualTo("itemType", 2);
        return empSocItemDAO.selectByExample(example);
    }

    @Override
    public List<EmpSocItemDO> selectSocByEmpSocInfoId(String empSocInfoId, String siteId) {
        Example example = new Example(EmpSocItemDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("empSocId", empSocInfoId)
                .andEqualTo("itemType", 1);
        return empSocItemDAO.selectByExample(example);
    }

    @Override
    public BigDecimal[] syncFillEmpSocInfoItem(String itemName, String empSocInfoId, String cardinalityDefault,
                                               String amountCompany, String amountPersonal, String proportionCompany,
                                               String proportionPersonal, List<EmpSocItemDO> empSocItemList,
                                               Map<String, QingDaoCardinalityDefaultDTO> cardinalityDefaultGroupType,
                                               Integer type, TokenUser tokenUser) {
        BigDecimal[] bigDecimals = new BigDecimal[2];
        EmpSocItemDO empSocItemDO = new EmpSocItemDO();
        empSocItemDO.setItemName(itemName);
        empSocItemDO.setEmpSocId(empSocInfoId);
        empSocItemDO.setItemType(type);
        empSocItemDO.setCardinalityDefault(new BigDecimal(cardinalityDefault));
        empSocItemDO.setAmountCompany(new BigDecimal(amountCompany));
        empSocItemDO.setAmountPersonal(new BigDecimal(amountPersonal));
        empSocItemDO.setMantissaProcCompany(NOT_PROCESSING.getValue());
        empSocItemDO.setMantissaProcPersonal(NOT_PROCESSING.getValue());
        empSocItemDO.setSort(0);
        if (!StringUtils.isEmpty(proportionCompany)) {
            empSocItemDO.setPersentCompany(new BigDecimal(proportionCompany));
        }
        if (!StringUtils.isEmpty(proportionPersonal)) {
            empSocItemDO.setPersentPersonal(new BigDecimal(proportionPersonal));
        }
        if (cardinalityDefaultGroupType != null) {
            empSocItemDO.setPersentPersonal(new BigDecimal(cardinalityDefaultGroupType.get(itemName).getGrjfbl()));
            empSocItemDO.setPersentCompany(new BigDecimal(cardinalityDefaultGroupType.get(itemName).getDwjfbl()));
        }
        empSocItemDO.setSiteId(tokenUser.getSiteId());
        empSocItemDO.setCreateUserId(tokenUser.getUserId());
        empSocItemDO.setGmtCreate(new Date());
        empSocItemDO.setModifiedUserId(tokenUser.getUserId());
        empSocItemDO.setGmtModified(new Date());
        empSocItemDO.setValid(true);
        if (empSocItemList != null) {
            empSocItemList.add(empSocItemDO);
        } else {
            empSocItemService.save(empSocItemDO, tokenUser.getSiteId(), tokenUser.getUserId());
        }
        // index = 0 时 公司金额
        bigDecimals[0] = empSocItemDO.getAmountCompany();
        // index = 1 时 个人金额
        bigDecimals[1] = empSocItemDO.getAmountPersonal();
        return bigDecimals;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void deleteByEmpSocInfoIdAndItemType(String empSocInfoId, Integer itemType, String siteId) {
        Example example = new Example(EmpSocItemDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("empSocId", empSocInfoId)
                .andEqualTo("itemType", itemType);
        empSocItemDAO.deleteByExample(example);
    }

    @Override
    public List<EmpSocItemDO> selectByEmpSocIdAndItemType(String empSocId, Integer itemType, String siteId) {
        Example example = new Example(EmpSocItemDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andEqualTo("empSocId", empSocId)
                .andEqualTo("itemType", itemType);
        return empSocItemDAO.selectByExample(example);
    }

    @Override
    public Integer updateEmpSocItemByEmpSocInfoIds(List<String> empSocInfoList, TokenUser tokenUser) {
        return empSocItemDAO.updateEmpSocItemByEmpSocInfoIds(empSocInfoList, new Date(), tokenUser.getUserId());
    }

    @Override
    public List<EmpSocItemVO> selectByEmpSocIdList(List<String> empSocInfoIdList, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(empSocInfoIdList)) {
            return new ArrayList<>();
        }
        List<EmpSocInfoVO> empSocInfoList =
                empSocInfoService.selectByIdListAndSetIdCard(empSocInfoIdList, tokenUser);
        Map<String, EmpSocInfoVO> empSocInfoMap =
                empSocInfoList.stream().collect(Collectors.toMap(EmpSocInfoVO::getId, v -> v));
        Example example = new Example(EmpSocItemDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId())
                .andIn("empSocId", empSocInfoIdList);
        List<EmpSocItemDO> empSocItemList = empSocItemDAO.selectByExample(example);
        return empSocItemList.stream().map(empSocItemDO -> {
            EmpSocItemVO empSocItemVO = empSocItemDO.to(EmpSocItemVO.class);
            empSocItemVO.setIdCard(empSocInfoMap.get(empSocItemVO.getEmpSocId()).getIdCard());
            empSocItemVO.setEmpName(empSocInfoMap.get(empSocItemVO.getEmpSocId()).getEmpName());
            empSocItemVO.setEmpId(empSocInfoMap.get(empSocItemVO.getEmpSocId()).getEmpId());
            return empSocItemVO;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void deleteByDoList(List<EmpSocItemDO> deleteList) {
        List<String> itemIdList = deleteList.stream().map(EmpSocItemDO::getId).collect(Collectors.toList());
        Example example = new Example(EmpSocItemDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andIn("id", itemIdList);
        empSocItemDAO.deleteByExample(example);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void deleteBySocInfoId(String empSocInfoId) {
        Example example = new Example(EmpSocItemDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("empSocId", empSocInfoId);
        empSocItemDAO.deleteByExample(example);
    }

    @Override
    public void updateItemCardinality(Map<String, String> dataMap, List<EmpSocItemDO> empSocItemList,
                                      Boolean onlySocAmount, TokenUser tokenUser) {
        Map<String, EmpSocItemDO> itemMap = empSocItemList.stream()
                .collect(Collectors.toMap(EmpSocItemDO::getItemName, v -> v));
        for (String itemName : dataMap.keySet()) {
            EmpSocItemDO empSocItemDO = itemMap.get(itemName);
            if (!ObjectUtils.isEmpty(empSocItemDO)) {
                String cardinalityDefaultStr = dataMap.get(itemName);
                if (!StringUtils.isEmpty(cardinalityDefaultStr)) {
                    BigDecimal cardinalityDefault = new BigDecimal(cardinalityDefaultStr);
                    empSocItemDO.setCardinalityDefault(cardinalityDefault);
                    if (!onlySocAmount) {
                        empSocItemDO.setAmountCompany(empSocTransformService.mantissaProcessing(
                                cardinalityDefault.multiply(empSocItemDO.getPersentCompany()
                                        .multiply(new BigDecimal("0.01"))), empSocItemDO.getMantissaProcCompany()));
                        empSocItemDO.setAmountPersonal(empSocTransformService.mantissaProcessing(
                                cardinalityDefault.multiply(empSocItemDO.getPersentPersonal()
                                        .multiply(new BigDecimal("0.01"))), empSocItemDO.getMantissaProcPersonal()));
                    }
                    updateByIdSelective(empSocItemDO);
                }

            }
        }
    }

    @Override
    public Integer getTypeByItemName(String itemName) {
        Example example = new Example(EmpSocItemDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("itemName", itemName);
        Page<EmpSocItemDO> empSocItemDOPage = empSocItemDAO.selectPageByExample(example, 1, 1);
        List<EmpSocItemDO> empSocItem = empSocItemDOPage.getEntities();
        if (!ObjectUtils.isEmpty(empSocItem)) {
            return empSocItem.get(0).getItemType();
        }
        return null;
    }

    @Override
    public List<EmpSocItemDO> selectBySite(TokenUser tokenUser) {
        Example example = new Example(EmpSocItemDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId());
        return empSocItemDAO.selectByExample(example);
    }

    /**
     * 根据查询参数，构建example
     *
     * @param empSocItemQuery 查询参数
     * @param siteId          所属站点id
     * @return example
     */
    private Example buildExample(EmpSocItemQuery empSocItemQuery, String siteId) {
        Example example = new Example(EmpSocItemDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (empSocItemQuery.getEmpSocId() != null) {
            example.and().andEqualTo("empSocId", empSocItemQuery.getEmpSocId());
        }
        if (empSocItemQuery.getItemType() != null) {
            example.and().andEqualTo("itemType", empSocItemQuery.getItemType());
        }
        if (empSocItemQuery.getItemName() != null) {
            example.and().andEqualTo("itemName", empSocItemQuery.getItemName());
        }
        if (empSocItemQuery.getCardinalityDefaultStart() != null &&
                empSocItemQuery.getCardinalityDefaultEnd() != null) {
            example.and().andBetween("cardinalityDefault", empSocItemQuery.getCardinalityDefaultStart(),
                    empSocItemQuery.getCardinalityDefaultEnd());
        }
        if (empSocItemQuery.getCardinalityMinStart() != null &&
                empSocItemQuery.getCardinalityMinEnd() != null) {
            example.and().andBetween("cardinalityMin", empSocItemQuery.getCardinalityMinStart(),
                    empSocItemQuery.getCardinalityMinEnd());
        }
        if (empSocItemQuery.getCardinalityMaxStart() != null &&
                empSocItemQuery.getCardinalityMaxEnd() != null) {
            example.and().andBetween("cardinalityMax", empSocItemQuery.getCardinalityMaxStart(),
                    empSocItemQuery.getCardinalityMaxEnd());
        }
        if (empSocItemQuery.getPersentCompanyStart() != null &&
                empSocItemQuery.getPersentCompanyEnd() != null) {
            example.and().andBetween("persentCompany", empSocItemQuery.getPersentCompanyStart(),
                    empSocItemQuery.getPersentCompanyEnd());
        }
        if (empSocItemQuery.getPersentPersonalStart() != null &&
                empSocItemQuery.getPersentPersonalEnd() != null) {
            example.and().andBetween("persentPersonal", empSocItemQuery.getPersentPersonalStart(),
                    empSocItemQuery.getPersentPersonalEnd());
        }
        if (empSocItemQuery.getAmountCompanyStart() != null &&
                empSocItemQuery.getAmountCompanyEnd() != null) {
            example.and().andBetween("amountCompany", empSocItemQuery.getAmountCompanyStart(),
                    empSocItemQuery.getAmountCompanyEnd());
        }
        if (empSocItemQuery.getAmountPersonalStart() != null &&
                empSocItemQuery.getAmountPersonalEnd() != null) {
            example.and().andBetween("amountPersonal", empSocItemQuery.getAmountPersonalStart(),
                    empSocItemQuery.getAmountPersonalEnd());
        }
        if (empSocItemQuery.getMantissaProcCompany() != null) {
            example.and().andEqualTo("mantissaProcCompany", empSocItemQuery.getMantissaProcCompany());
        }
        if (empSocItemQuery.getMantissaProcPersonal() != null) {
            example.and().andEqualTo("mantissaProcPersonal", empSocItemQuery.getMantissaProcPersonal());
        }
        if (empSocItemQuery.getSort() != null) {
            example.and().andEqualTo("sort", empSocItemQuery.getSort());
        }
        if (empSocItemQuery.getItemRemark() != null) {
            example.and().andEqualTo("itemRemark", empSocItemQuery.getItemRemark());
        }
        // 排序
        ExampleKit.setExampleOrder(example, empSocItemQuery.getOrders());
        return example;
    }
}




